package com.qianniu.napi.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.google.common.base.Strings;
import com.qianniu.napi.admin.entity.*;
import com.qianniu.napi.admin.mapper.MconfigExtMapper;
import com.qianniu.napi.admin.service.*;
import com.qianniu.napi.common.config.Constants;
import com.qianniu.napi.common.util.HttpUtil;
import com.qianniu.napi.common.util.ObjectUtil;
import org.redisson.api.RBucket;
import org.redisson.api.RList;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class RedisServiceImpl implements IRedisService {

    private static final Logger logger = LoggerFactory.getLogger(RedisServiceImpl.class);
    @Autowired
    private RedissonClient redis;
    @Autowired
    private IUserService userService;
    @Autowired
    private IMerchantService merchantService;
    @Autowired
    private IMerchantAppService merchantAppService;
    @Autowired
    private IMerchantConfigService merchantConfigService;
    @Autowired
    private MconfigExtMapper mconfigExtMapper;

    public Boolean isnull(String rkey){
        logger.info("=========isnull get rkey=" + rkey);
        RBucket<String> bucket = redis.getBucket(rkey);
        return Strings.isNullOrEmpty(bucket.get());
    }

    public Boolean isExists(String rkey){
        logger.info("=========isnull get rkey=" + rkey);
        RBucket<String> bucket = redis.getBucket(rkey);
        return bucket.isExists();
    }

    public <T> T get(String rkey) {
        logger.info("=========get rkey=" + rkey);
        RBucket<T> bucket = redis.getBucket(rkey);
        if (!bucket.isExists()) return null;
        T t = bucket.get();
        return t;
    }

    public <T> void set(String rkey, T t) {
        logger.info("=========set rkey=" + rkey);
        RBucket<T> bucket = redis.getBucket(rkey);
        if (t == null) {
            logger.info("=========set rkey t=null");
            return;
        }
        bucket.set(t);
    }

    public <T> void setList(String rkey,T t) {
        logger.info("=========set rkey=" + rkey);
        RList<T> bucket = redis.getList(rkey);
        bucket.add(t);
    }

    public <T> List<T> getList(String rkey){
        logger.info("=========getList rkey=" + rkey);
        RList<T> bucket = redis.getList(rkey);
        List<T> list = bucket.get();
        return list;
    }

    public <T> void set(String rkey, T t, long ts, TimeUnit tu) {
        logger.info("=========set rkey withtimeout=" + rkey);
        RBucket<T> bucket = redis.getBucket(rkey);
        if (t == null) {
            logger.info("=========set rkey t=null");
            return;
        }
        bucket.set(t, ts, tu);
    }

    public <T> void del(String rkey) {
        logger.info("=========del rkey=" + rkey);
        RBucket<T> bucket = redis.getBucket(rkey);
        if (bucket.isExists()) bucket.delete();
    }

    public User getUser() {
        logger.info("=========getUser");
        // 1、获取mapp
        Long uid = ObjectUtil.getUid();
        if (uid == null) return null;

        String rkey = Constants.REDIS_APP_USER + uid;
        logger.info("=========getUser rkey=" + rkey);
        RBucket<User> bucket = redis.getBucket(rkey);

        User user = bucket.isExists() ? bucket.get() : userService.selectById(uid);
        if(user==null)return null;

        if (bucket.get() == null) bucket.set(user, 30, TimeUnit.MINUTES);

        String rgkey = Constants.REDIS_APP_USER_GUID + user.getGuid();
        RBucket<User> rgbucket = redis.getBucket(rgkey);
        if (rgbucket.get() == null) rgbucket.set(user, 30, TimeUnit.MINUTES);

        return user;
    }

    public void delUser() {
        logger.info("=========getUser");
        // 1、获取mapp
        Long mpid = ObjectUtil.getMpid();
        Long uid = ObjectUtil.getUid();

        delUser(uid);
    }

    public void delUser(Long uid) {
        logger.info("=========getUser");
        // 1、获取mapp
        if (uid == null) return;

        String rkey = Constants.REDIS_APP_USER + uid;
        logger.info("=========getUser rkey=" + rkey);
        RBucket<User> bucket = redis.getBucket(rkey);

        if (bucket.isExists()) bucket.delete();
    }

    public User getUserByGuid(String guid) {
        logger.info("=========getUserByGuid");
        // 1、获取mapp
        String rgkey = Constants.REDIS_APP_USER_GUID + guid;
        RBucket<User> rgbucket = redis.getBucket(rgkey);
        logger.info("=========getUserByGuid rgkey=" + rgkey);
        User user = rgbucket.isExists() ? rgbucket.get() :
                userService.selectOne(new EntityWrapper<User>().eq("guid", guid));
        if (rgbucket.get() == null) rgbucket.set(user, 30, TimeUnit.MINUTES);

        return user;
    }

    public MerchantApp getMApp() {
        logger.debug("=========getMApp()");
        Long mpid = ObjectUtil.getMpid();
        logger.debug("=========getMApp() mpid=" + mpid);
        if (mpid == null) return null;

        return getMApp(mpid);
    }

    public MerchantApp getMApp(Long mpid) {
        logger.info("=========getMApp(mpid)");
        String rkey = Constants.REDIS_MERCHANT_APP + mpid;
        logger.info("=========getMApp rkey=" + rkey);
        MerchantApp mapp = null;
        RBucket<MerchantApp> bucket = redis.getBucket(rkey);
        try {
            mapp = bucket.isExists() && bucket.get().getId() > 0 ? bucket.get() : merchantAppService.selectOne(new EntityWrapper<MerchantApp>()
                    .setSqlSelect("id,name,appid,mid,mchid,mpcode,mcode,sid,appsecret,paykey,aeskey,aesiv,token,asmpid,iscdn," +
                            "app_type appType,version_type version,kefuzj,kefu1,kefu2,smsappid,smsappkey,aspaympid,servmchid,servappid").eq("id", mpid));
            if (bucket.get() == null && mapp != null) bucket.set(mapp);
        } catch (Exception e) {
            logger.error("======getMconfig error", e);
        }
        return mapp;
    }

    public Merchant getMerchant(Long mid) {
        logger.info("=========getMerchant(mid)");
        String rkey = Constants.REDIS_MERCHANT + mid;
        logger.info("=========getMerchant rkey=" + rkey);
        Merchant merchant = null;
        RBucket<Merchant> bucket = redis.getBucket(rkey);
        try {
            merchant = bucket.isExists() && bucket.get().getId() > 0 ? bucket.get() : merchantService.selectOne(new EntityWrapper<Merchant>()
                    .setSqlSelect("id,name,mcode,iscdn").eq("id", mid));
            if (bucket.get() == null && merchant != null) bucket.set(merchant);
        } catch (Exception e) {
            logger.error("======getMconfig error", e);
        }
        return merchant;
    }

    public MerchantConfig getMconfig() {
        logger.debug("=========getMconfig()");
        return getMconfig(ObjectUtil.getMpid());
    }

    public MerchantConfig getMconfig(Long mpid) {
        logger.debug("=========getMconfig((Long mpid="+mpid+"))");
        String rkey = Constants.REDIS_MERCHANT_CONFIG + mpid;
        logger.debug("=========getMconfig mpid=" + mpid);
        logger.debug("=========getMconfig rkey=" + rkey);
        MerchantConfig mconfig = null;
        try {
            RBucket<MerchantConfig> bucket = redis.getBucket(rkey);
            mconfig = bucket.isExists() && bucket.get().getId() > 0 ? bucket.get() : merchantConfigService.selectOne(new EntityWrapper<MerchantConfig>().eq("mpid", mpid));

            logger.debug("=========mconfig=" + JSON.toJSONString(mconfig));
            if (bucket.get() == null && mconfig != null) bucket.set(mconfig);
        } catch (Exception e) {
            logger.error("======getMconfig error", e);
        }
        return mconfig;
    }

    public MconfigExt getMconfigExt(Long mpid) {
        if(mpid==null)return null;
        logger.debug("=========getMconfigExt((Long mpid="+mpid+"))");
        String rkey = Constants.REDIS_MERCHANT_CONFIG_EXT + mpid;
        logger.debug("=========getMconfigExt mpid=" + mpid);
        logger.debug("=========getMconfigExt rkey=" + rkey);
        MconfigExt mconfigext = null;
        try {
            RBucket<MconfigExt> bucket = redis.getBucket(rkey);
            MconfigExt q = new MconfigExt();
            q.setMpid(mpid);

            mconfigext = bucket.isExists() && bucket.get().getMpid().intValue() > 0 ? bucket.get() : mconfigExtMapper.selectOne(q);

            logger.debug("=========mconfig=" + JSON.toJSONString(mconfigext));
            if (bucket.get() == null && mconfigext != null) bucket.set(mconfigext);
        } catch (Exception e) {
            logger.error("======getMconfig error", e);
        }
        return mconfigext;
    }

    public String getWxtoken() {
        logger.info("=========getWxtoken");
        // 1、获取mapp
        MerchantApp mapp = getMApp();
        if (mapp == null) return null;

        String rkey = Constants.REDIS_WX_TOKEN + mapp.getAppid();
        RBucket<String> bucket = redis.getBucket(rkey);
        String token = bucket.get();
        if (!Strings.isNullOrEmpty(token)) return token;

        try {
            String url = Constants.WX_URL_TOKEN.replace("APPID", mapp.getAppid()).replace("SECRET", mapp.getAppsecret());
            String rt = HttpUtil.sendGet(url, null);
            JSONObject json = JSONObject.parseObject(rt);
            if (json.getString("access_token") != null || json.getString("access_token") != "") {
                token = json.getString("access_token");
                Integer expires = json.getInteger("expires_in");
                bucket.set(token, expires, TimeUnit.SECONDS);
            } else {
                return null;
            }
        } catch (Exception e) {
            logger.error("# 获取 token 出错... e:" + e);
            return null;
        }
        logger.info("=========token=" + token);
        return token;
    }

    public String getWxtoken(String mpid) {

        if (Strings.isNullOrEmpty(mpid)) return "";
        MerchantApp mapp = getMApp(Long.valueOf(mpid));
        if (mapp == null || Strings.isNullOrEmpty(mapp.getAppid())) return "";

        String rkey = Constants.REDIS_WX_TOKEN + mapp.getAppid();
        RBucket<String> buckets = redis.getBucket(rkey);
        String token = buckets.get();
        if (!Strings.isNullOrEmpty(token)) return token;

        try {
            String url = Constants.WX_URL_TOKEN.replace("APPID", mapp.getAppid()).replace("SECRET", mapp.getAppsecret());
            String rt = HttpUtil.sendGet(url, null);
            JSONObject json = JSONObject.parseObject(rt);
            if (json.getString("access_token") != null || json.getString("access_token") != "") {
                token = json.getString("access_token");
                Integer expires = json.getInteger("expires_in");
                buckets.set(token, expires, TimeUnit.SECONDS);
            } else {
                return null;
            }
        } catch (Exception e) {
            logger.error("# 获取 token 出错... e:" + e);
            return null;
        }
        logger.info("=============================================getWxtoken token=" + token);
        return token;
    }

    public String getWxactoken(String mpid) {
        logger.info("=========getWxactoken");
        // 1、获取mapp
        MerchantApp mapp = getMApp();
        if(mapp==null) return null;

        String token = mapp.getToken();
        logger.info("=========token=" + token);
        return token;
    }

}
